import QtQuick 2.0
import VPlay 2.0
import "entities"
import QtSensors 5.1

SceneBase {
  id: scene
  // this is important, as it serves as the reference size for the mass of the phyiscs objects, because the mass of a body depends on the width of its images
  // use 480x320 (for landscape games) or 320x480 (for portrait games), as it then works on smaller devices as well
  // if you only want to target tablets, this size might be increased to e.g. 1024x768 when targeting iPad-only
  // when the screen size is bigger than the logical scene size defined here (e.g. 800x480), the content will be scaled automatically with the default scalemode "letterbox"
  // the scene can be placed in the bigger window with the properties sceneAlignmentX & sceneAlignmentY (both default to center)
  // so to use the remaining screen size and not show black borders around the edges, use a bigger background image
  // the recommended maximum background size is 576x368 for sd-images, and 1152x736 for hd-images and 2304x1472 for hd2-images
  // these factors are calculated by starting with a 3:2 aspect ratio (480x320) and considering the worst aspect ratios 16:9 and 4:3
  // width & height are set for all scenes in this game in SceneBase
  //width: 320
  //height: 480

  property alias level: level
  property alias player: level.player
  property alias entityContainer: level

  property real sensorMultiplicator: -1
  property real test: 5

  property real gravityProp: -40


  EditableComponent {
      editableType: "Balancing2"
      properties : {
          "sensorMultiplicator": {"min": 1, "max": 20, "label": "sensorMultiplicator"},
          "gravityProp": {"min": -100, "max": 0, "label": "gravityProp"},
          "test": {"min": 1, "max": 20, "label": "does nothing"}
      }
  }

  // make 1 grid (so 1 block and the player size) 48 logical px - a platform has this size, so 320/48= 6.6 can be displayed in one scene
  gridSize: 48//32

  // place it on bottom, because otherwise it would be unfair compared to different devices because the player would see more to the bottom playfield!
  sceneAlignmentY: "bottom"

  // for performance-testing, if the score should updated every frame with the y value of the level
  // it is set to false, because updating a static text every frame is very poor for performance, because a texture is generated every frame!
  // thus, if this flag is set to false the score is only updated every 10th frame which speeds things up
  property bool enableConstantScoreTextUpdating: false

  onBackPressed: {
    // TODO: instead of navigating to main without any warning, show an pause screen to avoid unintended exit of the game
    // it is important to call stopGame() here, because otherwise the entities would not be deleted!
    level.stopGame();
    window.state = "main"
  }

  // allows collision detection between the entities, so if the player collides with platforms or the corn, and for removal of the out-of-scene entities
  PhysicsWorld {
    // this id gets used in Level, to test if a new platform or window can be built on the new position or if there is an entity already
    id: physicsWorld
    // this puts it on top of all other items for the physics debug renderer
    z: 1

    // for physics-based games, this should be set to 60!
    updatesPerSecondForPhysics: 60
    // make objects fall faster by increasing gravity
    gravity.y: gravityProp;

    // this should be increased so it looks good, by default it is set to 1 to save performance
    velocityIterations: 5
    positionIterations: 5

    //y: level.y // uncomment this, if you want the physics world move with the level - this is only for testing the debugDraw, and has no effect on the game logic ans the physics positions are not mapped back to the physicsWorld!
  }

  Level {
    id: level

    onGameLost: {
      console.debug("SpacyJumpScene: gameLost()");
      level.stopGame();
      // lastScore is used in GameOverScreen to check if a new highscore is reached
      lastScore = player.totalScore;
      // Increment the player's death count
      player.deaths++;
      // change to state gameOver showing the GameOverScene - in the SceneBase a crossfade effect is implemented
      window.state = "gameOver"
    }
  }

  // this allows usage of the left and right keys on desktop systems or mobiles with physical keyboards
  // focus must be set to visible, not just to true, because when the scene gets invisible, it looses focus and would never get set to true again!  
  // forward the input to the controller of the player
  Keys.forwardTo: player.controller

  Image {
    id: flames
    anchors.bottom: scene.bottom
    width: level.width
    height: 50
    source: "../assets/img/flames.png"
  }

  Image {
      id: cloud
      anchors.top: scene.gameWindowAnchorItem.top
      width: level.width
      height: 50
      source: "../assets/img/clouds.png"
    }

//  // input graphics - the handling of the input is done below in the MouseArea
  Image {
    id: arrowLeft
    source: "../assets/img/arrow-left.png"
    opacity: 0.5
    width: 48
    height: 48
    anchors {
      left: scene.gameWindowAnchorItem.left
      bottom: scene.gameWindowAnchorItem.bottom
      leftMargin: 10
      bottomMargin: 10
    }
  }
  Image {
    id: arrowRight
    source: "../assets/img/arrow-left.png"
    opacity: 0.5
    width: 48
    height: 48
    mirror: true
    anchors {
      right: scene.gameWindowAnchorItem.right
      bottom: scene.gameWindowAnchorItem.bottom
      rightMargin: 10
      bottomMargin: 10
    }
  }

  MultiPointTouchArea {
    // use the full window as control item, press anywhere on the left half for steering left, on the right half for steering right
    anchors.fill: scene.gameWindowAnchorItem

    onPressed: {
      console.debug("onPressed, mouseX", touchPoints[0].x)
      if(touchPoints[0].x > scene.gameWindowAnchorItem.width/2)
        player.controller.xAxis = 1;
      else
        player.controller.xAxis = -1;
    }
//    onPositionChanged: {
//      if(mouseX > scene.gameWindowAnchorItem.width/2)
//        player.controller.xAxis = 1;
//      else
//        player.controller.xAxis = -1;
//    }

    onReleased: {
        player.controller.xAxis = 0;
        player.controller.yAxis = 1;
        // When starting the timer it is triggered after 500ms
        timerJump.restart();
    }
  }

  Accelerometer {
   id: accelerometer
      onReadingChanged: {
      // connect the TwoAxisController with the acceleration data
        player.controller.xAxis = reading.x * sensorMultiplicator;
      }
  }

  Timer {
    id: timerJump
      interval: 100;
      onTriggered: {
        player.controller.yAxis = 0;
      }
  }

  Text {
    x: 5
    // place it on top of the window, not on top of the logical scene
    anchors.top: scene.gameWindowAnchorItem.top
    anchors.topMargin: 30

    text: "Score: " + player.totalScore
    font.family: fontHUD.name
    font.pixelSize: 22
    color: "white"
  }

  Text {
    id: notificationText

    anchors.top: scene.gameWindowAnchorItem.top
    anchors.topMargin: 35
    anchors.horizontalCenter: parent.horizontalCenter;
    text: "BigJump!\n";
    font.family: fontHUD.name
    verticalAlignment: Text.AlignVCenter
    horizontalAlignment: Text.AlignHCenter

    font.pixelSize: 30
    color: "white"
    visible: false
  }

  // gets called by SpacyJumpMain when this scene gets active
  // starts a game again - stopGame() was called before so it is save to call that here
  function enterScene() {
      if(settings.getValue("accelerometerEnabled")) {
          console.debug("hide buttons")
        arrowLeft.visible = false
        arrowRight.visible = false
      } else {
          console.debug("show buttons")
        arrowLeft.visible = true
        arrowRight.visible = true
      }

    level.startGame();
  }


  // ------------------- debugging-only code ------------------- //

  // this button is only for testing and only visible in debug mode
  // it shows the ingameMenu to quickly restart the game and test different performance options
  SimpleButton {
    id: hud
    width: 64
    height: 64
    // place it on top of the window, not on top of the logical scene
    anchors.top: scene.gameWindowAnchorItem.top
    anchors.right: scene.gameWindowAnchorItem.right
    visible: true //system.debugBuild // only display in debug mode - the menu button for ingame testing should not be visible in retail builds for the store (and also not in release builds)
    text: "Menu"
    onClicked: {
      console.debug("Menu button clicked")
      // this activates the ingameMenu state, which will show the IngameMenu item
      scene.state = "ingameMenu"

      //window.state = "gameOver" // uncommment this for testing the state-changes when pressing the menu button
    }
  }

  SimpleButton {
    id: hideItemEditor
    width: 64
    height: 64
    // place it on top of the window, not on top of the logical scene
    anchors.top: scene.gameWindowAnchorItem.top
    anchors.right: scene.gameWindowAnchorItem.right
    anchors.topMargin: 65
//    visible: system.debugBuild // only display in debug mode - the menu button for ingame testing should not be visible in retail builds for the store (and also not in release builds)
    text: "hide"
    onClicked: {
      console.debug("hide button clicked")
        itemEditor.visible = !itemEditor.visible;
      // this activates the ingameMenu state, which will show the IngameMenu item

      //window.state = "gameOver" // uncommment this for testing the state-changes when pressing the menu button
    }
    visible: false
  }

  // this gets only displayed when the menu button is pressed, which is only allowed in debug builds
  IngameMenu {
    id: ingameMenu
    // in the default state, this should be invisible!
    visible: false
    anchors.centerIn: parent
  }

  ItemEditor {
        id: itemEditor
        opacity: 0.7
        z:1
        width: 150;
        height: parent.height
        visible: false

        // start visible
  }

  // the ingameMenue state is only enabled when in debug mode and when the menu button is pressed
  onStateChanged: console.debug("Scene.state changed to", state)
  states: [
    State {
      name: ""
      StateChangeScript {
        script: {
          console.debug("scene: entered state ''")
          level.resumeGame();
        }
      }
    },
    State {
      name: "ingameMenu"
      PropertyChanges { target: ingameMenu; visible: true}
      StateChangeScript {
        script: {
          console.debug("scene: entered state 'ingameMenu'")
          level.pauseGame();
        }
      }
    }

  ]
}
